﻿namespace Amazon.Checkout.Settings
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    using Models;

    using Orchard;
    using Orchard.ContentManagement;
    using Orchard.ContentManagement.MetaData;
    using Orchard.ContentManagement.MetaData.Builders;
    using Orchard.ContentManagement.MetaData.Models;
    using Orchard.ContentManagement.ViewModels;
    using Orchard.Localization;
    using Orchard.UI.Notify;

    public class CheckoutByAmazonButtonPartSettingsHook : ContentDefinitionEditorEventsBase
    {
        private readonly IOrchardServices orchardServices;

        private List<string> possibleMappings;

        public CheckoutByAmazonButtonPartSettingsHook(IOrchardServices orchardServices)
        {
            this.orchardServices = orchardServices;
            this.T = NullLocalizer.Instance;
        }

        public Localizer T { get; set; }

        public Type GetTypeFromName(string name)
        {
            var appAssemblies = AppDomain.CurrentDomain.GetAssemblies();

            foreach (var assembly in appAssemblies)
            {
                try
                {
                    foreach (var type in assembly.GetTypes().Where(type => type.Name.Equals(name)))
                    {
                        return type;
                    }
                }
                catch (Exception)
                {
                }
            }

            return null;
        }

        public override IEnumerable<TemplateViewModel> TypeEditor(ContentTypeDefinition definition)
        {
            this.possibleMappings = new List<string>();

            foreach (var part in definition.Parts)
            {
                if (part.PartDefinition.Name != typeof(CheckoutByAmazonButtonPart).Name)
                {
                    part.PartDefinition.Fields.ToList().ForEach(f => this.possibleMappings.Add(f.Name));
                }
            }

            foreach (var partName in definition.Parts.Select(part => part.PartDefinition.Name))
            {
                if (partName != typeof(CheckoutByAmazonButtonPart).Name)
                {
                    try
                    {
                        var type = this.GetTypeFromName(partName);

                        if (type == null) { continue; }

                        foreach (var property in type.GetProperties())
                        {
                            this.possibleMappings.Add(partName + "." + property.Name);
                        }
                    }
                    catch (Exception)
                    {
                    }
                }
            }

            return base.TypeEditor(definition);
        }

        public override IEnumerable<TemplateViewModel> TypePartEditor(ContentTypePartDefinition definition)
        {
            if (definition.PartDefinition.Name != typeof(CheckoutByAmazonButtonPart).Name)
            {
                yield break;
            }

            var model = definition.Settings.GetModel<CheckoutByAmazonButtonPartSettings>();
            var settingsPart = this.orchardServices.WorkContext.CurrentSite.As<SiteSettingsPart>();

            model.ShowWarning = !settingsPart.AmazonInitializedButton();

            if (model.ShowWarning)
            {
                this.orchardServices.Notifier.Error(this.T("The Checkout by Amazon module is not properly configured. Please go to Settings > Amazon to provide the required settings."));
            }

            var mappingsList = new List<string> { string.Empty };
            mappingsList.AddRange(this.possibleMappings);

            model.PossibleMappings = mappingsList;
            model.SetEmptyFieldsToDefaults();

            yield return DefinitionTemplate(model);
        }

        public override IEnumerable<TemplateViewModel> TypePartEditorUpdate(ContentTypePartDefinitionBuilder builder, IUpdateModel updateModel)
        {
            if (builder.Name != typeof(CheckoutByAmazonButtonPart).Name)
            {
                yield break;
            }

            var model = new CheckoutByAmazonButtonPartSettings { PossibleMappings = this.possibleMappings };
            updateModel.TryUpdateModel(model, typeof(CheckoutByAmazonButtonPartSettings).Name, null, null);

            builder.WithSetting("CheckoutByAmazonButtonPartSettings.ExpressCheckout", model.ExpressCheckout);
            builder.WithSetting("CheckoutByAmazonButtonPartSettings.ProductTitleMapping", model.ProductTitleMapping);
            builder.WithSetting("CheckoutByAmazonButtonPartSettings.ProductDescriptionMapping", model.ProductDescriptionMapping);
            builder.WithSetting("CheckoutByAmazonButtonPartSettings.ProductPriceMapping", model.ProductPriceMapping);
            builder.WithSetting("CheckoutByAmazonButtonPartSettings.ProductSkuMapping", model.ProductSkuMapping);
            builder.WithSetting("CheckoutByAmazonButtonPartSettings.ProductImageUrlMapping", model.ProductImageUrlMapping);

            yield return DefinitionTemplate(model);
        }
    }
}